Android recovery 模式下出于安全的考虑,一般禁止adb和adb shell 登陆。如果需要在recovery 模式下进行debug,需要做一些配置修改。
烧录user版本系统,进入recovery后,输入adb shell命令,提示
error: no devices/emulators found
我们先确认recovery.img是否包含有adb (adb的源码在/system/core/adb)
ls out/target/product/bullhead/recovery/root/sbin
adbd healthd recovery ueventd watchdogd
然后检查/bootable/recovery/etc/init.rc下和adbd相关的启动配置
service adbd /sbin/adbd --root_seclabel=u:r:su:s0 --device_banner=recovery
disabled
socket adbd stream 660 system system
seclabel u:r:adbd:s0
# Always start adbd on userdebug and eng builds
on property:ro.debuggable=1
write /sys/class/android_usb/android0/enable 1
start adbd
# Restart adbd so it can run as root
on property:service.adb.root=1
write /sys/class/android_usb/android0/enable 0
restart adbd
write /sys/class/android_usb/android0/enable 1
从上面可知init.rc 中adbd 是配置的,disabled 表示开机不启动,如 ro.debuggable 被置为1,那么adb 就会开启,或是service.adb.root设置为1,则重启adbd。
看下
mvim build/core/main.mk
ifeq (true,$(strip $(enable_target_debugging)))
# Target is more debuggable and adbd is on by default
ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1
# Enable Dalvik lock contention logging.
ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.lockprof.threshold=500
# Include the debugging/testing OTA keys in this build.
INCLUDE_TEST_OTA_KEYS := true
else # !enable_target_debugging
# Target is less debuggable and adbd is off by default
ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0
endif # !enable_target_debugging
关于enable_target_debugging
## user/userdebug ##
user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
enable_target_debugging := true
tags_to_install :=
ifneq (,$(user_variant))
# Target is secure in user builds.
ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1
ADDITIONAL_DEFAULT_PROPERTIES += security.perf_harden=1
ifeq ($(user_variant),user)
ADDITIONAL_DEFAULT_PROPERTIES += ro.adb.secure=1
endif
ifeq ($(user_variant),userdebug)
# Pick up some extra useful tools
tags_to_install += debug
else
# Disable debugging in plain user builds.
enable_target_debugging :=
endif
# Disallow mock locations by default for user builds
ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0
else # !user_variant
# Turn on checkjni for non-user builds.
ADDITIONAL_BUILD_PROPERTIES += ro.kernel.android.checkjni=1
# Set device insecure for non-user builds.
ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0
# Allow mock locations by default for non user builds
ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1
endif # !user_variant
可知默认为enable_target_debugging := true,根据user_variant的值如果为user,则enable_target_debugging :=,这又和TARGET_BUILD_VARIANT有关,此变量对应于VARIANT_CHOICES=(user userdebug eng)中的一个值,由我们来选择,相关的实现在/build/envsetup.sh中。
根据上面可知,编译时如果选择userdebug或是eng,则ro.debuggable=1,如果我们要在user下也开启这些功能,就需要修改设置
enable_target_debugging := true
ro.debuggable=0
重新编译recovery.img,刷机后,进入recovery,输入adb shell命令,提示:
Exec ‘/system/bin/sh’ failed:No such fileor directory(2)
表示没有sh这个文件,无法进入shell,检查ramdisk 文件系统 system 目录out/target/product/bullhead/recovery/root/system为空。(其实这个system是用来挂载Android的/system的,关于挂载后面会讲)
但我们知道boot.img下是可以的,看system/core/rootdir/init.rc检查boot.img 启动的init.rc。查找关于/sh的代码
service console /system/bin/sh
class core
console
disabled
user shell
group shell log
seclabel u:r:shell:s0
on property:ro.debuggable=1
# Give writes to anyone for the trace folder on debug builds.
# The folder is used to store method traces.
chmod 0773 /data/misc/trace
start console
所以依葫芦画瓢,我们在Recovery的/bootable/recovery/etc/init.rc添加上面的代码。
好了,虽然这一步会在Recovery启动时启动sh,但是Recovery里面没有这个文件啊(前面说了/system是个空目录,用来挂载系统的)。所以需要编译时创建这个文件,因此在/build/core/Makefile增加创建目录的代码和把系统sh拷贝到Recovery的对应目录下
define build-recoveryimage-target
@echo ----- Making recovery image ------
$(hide) mkdir -p $(TARGET_RECOVERY_OUT)
$(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/etc $(TARGET_RECOVERY_ROOT_OUT)/sdcard $(TARGET_RECOVERY_ROOT_OUT)/tmp
...
# 添加下面代码
$(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system/bin
$(hide) cp -r $(PRODUCT_OUT)/system/bin/sh $(TARGET_RECOVERY_ROOT_OUT)/system/bin/
这里有个问题,就是clean掉项目重新编译的时候,系统的sh还没有生成,所以这里的拷贝操作会因为找不到sh文件而出错,需要调整代码位置。
但这样还是不行,在recovery模式下,二进制文件都是静态连接方式,recovery模式中没有共享库,缺动态链接库加载器(/system/bin/linker,Android动态连接器linker与静态连接器ld)
检查sh 连接的动态库:
arm-linux-androideabi-objdump -x out/target/product/xxxx/system/bin/sh | grep NEEDED
NEEDED libc.so
知道需要改libc的编译。
所以需要修改/external/mksh/Android.mk
#LOCAL_SYSTEM_SHARED_LIBRARIES := libc
LOCAL_STATIC_LIBRARIES := libc
LOCAL_FORCE_STATIC_EXECUTABLE := true
再次编译recovery.img,刷机,进入Recovery模式后就可以使用adb shell了。
关于没有ls命令,这些命令不可用的原理和sh一样,可以自己试着去改。
Reference
https://blog.csdn.net/LoongEmbedded/article/details/67638687